package com.sushengren.easyword.handle;

import com.sushengren.easyword.anchor.PlaceholderAnchor;
import com.sushengren.easyword.enums.DataTypeEnum;
import com.sushengren.easyword.model.WriteData;
import org.apache.commons.collections4.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 写入数据标准化处理
 *
 * @author sushengren
 */
public class WriteDataNormalizeHandle {

    /**
     * 写入数据标准化
     *
     * <pre>
     * 1. 列表数据最少保持一条数据，缺少会自动创建空字符的数据
     * 2. 列表数据下的列key必须保持一致，缺少的key会自动创建一个空字符的写入数据
     * </pre>
     *
     * @param writeDataList 写入数据列表
     */
    public static void normalize(List<WriteData> writeDataList) {
        Map<String, Set<String>> listKeys = new HashMap<>();
        for (WriteData writeData : writeDataList) {
            listKeys(writeData, listKeys, "");
        }
        for (WriteData writeData : writeDataList) {
            normalize(writeData, listKeys, "");
        }
    }

    /**
     * 获取写入
     *
     * @param writeData 写入数据
     * @param result    结果
     * @param prefix    前缀
     */
    private static void listKeys(WriteData writeData, Map<String, Set<String>> result, String prefix) {
        if (!DataTypeEnum.LIST.equals(writeData.getDataType())) {
            return;
        }
        Set<String> keys = new HashSet<>();
        List<List<WriteData>> listValue = writeData.getListValue();
        if (!CollectionUtils.isEmpty(listValue)) {
            for (List<WriteData> dataList : listValue) {
                for (WriteData data : dataList) {
                    if (DataTypeEnum.LIST.equals(data.getDataType())) {
                        listKeys(data, result, data.getKey() + PlaceholderAnchor.FLAG_SPLIT);
                    }
                    if (data.getKey() != null) {
                        keys.add(data.getKey());
                    }
                }
            }
        }
        String key = prefix + writeData.getKey();
        result.computeIfAbsent(key, k -> new HashSet<>()).addAll(keys);
    }

    /**
     * 写入数据标准化
     */
    private static void normalize(WriteData writeData, Map<String, Set<String>> listKeys, String prefix) {
        if (!DataTypeEnum.LIST.equals(writeData.getDataType())) {
            return;
        }
        if (CollectionUtils.isEmpty(writeData.getListValue())) {
            writeData.setListValue(Collections.singletonList(new ArrayList<>()));
        }
        List<List<WriteData>> listValue = writeData.getListValue();
        for (List<WriteData> dataList : listValue) {
            for (WriteData data : dataList) {
                if (DataTypeEnum.LIST.equals(data.getDataType())) {
                    normalize(data, listKeys, data.getKey() + PlaceholderAnchor.FLAG_SPLIT);
                }
            }
        }
        for (List<WriteData> dataList : listValue) {
            Set<String> keys = listKeys.get(prefix + writeData.getKey());
            long count = dataList.stream().map(WriteData::getKey).distinct().count();
            if (count < keys.size()) {
                List<String> keyList = dataList.stream().map(WriteData::getKey).distinct().collect(Collectors.toList());
                for (String key : keys) {
                    if (!keyList.contains(key)) {
                        dataList.add(WriteData.emptyString(key));
                    }
                }
            }
        }
    }

}
